﻿using System;
using System.Linq;

namespace MEFTest
{
    /*
     * 需要引用：System.ComponentModel.Composition
     * 
     * 1、
     * 三步走：
     * 宿主MEF并组合部件、标记对象的导出、对象的导入使用。
     * 2、
     * 对象、对象的属性、字段、方法、事件等也可以通过[ImportAttribute]进行导入
     * 方法的导入和导出是通过匿名委托的方式实现的
     * 
     * 3、
     * MEF的延迟加载:
     * 我们知道，当装配一个组件的时候，当前组件里面的所有的Import的变量都自动去找到对应的Export而执行了实例化，
     * 有些时候，出于程序效率的考虑，不需要立即实例化对象，而是在使用的时候才对它进行实例化。MEF里面也有这种延迟加载的机制。
     * 
     * 讲到这里，我们再来看前面关于理解MEF的两个关键点：
     * （1）可扩展的库：由于MEF允许通过Import的方式直接导入对象、属性、方法等，试想，有人开发了一个组件，
     * 他们事先定义好了一系列的导出(Export)，我们只需要将它的组件引进来，使用Import的方式按照他们Export的约定导入对象即可，不用做其他复杂的配置。
     * （2）能更好的实现“松耦合”：比如我们项目按照面向接口编程的方式这样分层：UI层、BLL接口层、BLL实现层......
     * UI层只需要引用BLL接口层即可，我们在BLL实现层里面定义好Export的导出规则，然后再UI层里面使用Import导入BLL实现层的对象即可，
     * 这样UI层就不需要添加BLL实现层的引用。减少了dll之间的依赖。
     * 
 */
    class Program
    {
        

        static void Main(string[] args)
        {
            #region 对象导入
            var myProgram = new ObjectTest();
            myProgram.MyComposePart();
            var strRes = myProgram.car.Show("跑得快");
            Console.WriteLine(strRes);
            #endregion

            #region 属性导入
            var propertyTest = new PropertyTest();
            propertyTest.MyComposePart();
            string name = propertyTest._name;
            Console.WriteLine(name);

            #endregion

            #region 方法导入
            var methodTest = new MethodTest();
            methodTest.MyComposePart();
            methodTest.TestFuncImport("方法注入测试");
            #endregion

            #region 多个对象导入导出

            var manyObjectTest = new ManyObjectTest();
            manyObjectTest.MyComposePart();

            Console.WriteLine(manyObjectTest.lstPerson.Count());
            #endregion


            #region 延时加载

            var lazyObjectTest = new LazyObjectTest();
            lazyObjectTest.MyComposePart();

            Console.WriteLine(lazyObjectTest.Woman.Say("安红"));
            // 延时加载需要指定类型
            Console.WriteLine(lazyObjectTest.Lazyman.Value.Say("张三"));

            #endregion
            Console.Read();
        }
    }

    
}
